import requests
import time
import random
import execjs
from threading import Thread
from threading import Lock
from queue import Queue
import hashlib
from jsonpath import jsonpath
import json
import os
from PIL import Image,ImageTk
from tkinter import *
from concurrent.futures.thread import ThreadPoolExecutor 
class KuGou:
    def __init__(self,name):
        self.name=name
        self.headers1={
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
            'Cookie':'KuGooRandom=66191711779753402; kg_mid=dbe66a98c0694c4dffebdb2228182609; kg_dfid=11SGcS0c2kGQ06SxWR2Bw47W; ACK_SERVER_10017=%7B%22list%22%3A%5B%5B%22gzverifycode.service.kugou.com%22%5D%5D%7D; ACK_SERVER_10015=%7B%22list%22%3A%5B%5B%22gzlogin-user.kugou.com%22%5D%5D%7D; ACK_SERVER_10016=%7B%22list%22%3A%5B%5B%22gzreg-user.kugou.com%22%5D%5D%7D; kg_dfid_collect=d41d8cd98f00b204e9800998ecf8427e; Hm_lvt_aedee6983d4cfc62f509129360d6bb3d=1712191135,1712204808,1712218326,1712743932; kg_mid_temp=dbe66a98c0694c4dffebdb2228182609; KuGoo=KugooID=1487968463&KugooPwd=E19AC8E2797839BFE6892989708F1924&NickName=%u6e05%u98ce&Pic=http://imge.kugou.com/kugouicon/165/20220707/20220707143105836638.jpg&RegState=1&RegFrom=&t=42a909a834438be0137593611dbed7057e57fae20b86a43f6fc3eee2d08695f1&a_id=1014&ct=1712743944&UserName=%u006b%u0067%u006f%u0070%u0065%u006e%u0031%u0034%u0038%u0037%u0039%u0036%u0038%u0034%u0036%u0033&t1=; KugooID=1487968463; t=42a909a834438be0137593611dbed7057e57fae20b86a43f6fc3eee2d08695f1; a_id=1014; UserName=kgopen1487968463; mid=dbe66a98c0694c4dffebdb2228182609; dfid=11SGcS0c2kGQ06SxWR2Bw47W; Hm_lpvt_aedee6983d4cfc62f509129360d6bb3d=1712744161',
            'Referer':'https://www.kugou.com/',
            'authority':'complexsearch.kugou.com'
        }
        self.headers2={
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
            'Referer':'https://www.kugou.com/',
            'authority':'wwwapi.kugou.com'
        }
        self.headers3={
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0',
            'Cookie':'KuGooRandom=66191711779753402; kg_mid=dbe66a98c0694c4dffebdb2228182609; kg_dfid=11SGcS0c2kGQ06SxWR2Bw47W; ACK_SERVER_10017=%7B%22list%22%3A%5B%5B%22gzverifycode.service.kugou.com%22%5D%5D%7D; ACK_SERVER_10015=%7B%22list%22%3A%5B%5B%22gzlogin-user.kugou.com%22%5D%5D%7D; ACK_SERVER_10016=%7B%22list%22%3A%5B%5B%22gzreg-user.kugou.com%22%5D%5D%7D; kg_dfid_collect=d41d8cd98f00b204e9800998ecf8427e; Hm_lvt_aedee6983d4cfc62f509129360d6bb3d=1712191135,1712204808,1712218326,1712743932; kg_mid_temp=dbe66a98c0694c4dffebdb2228182609; KuGoo=KugooID=1487968463&KugooPwd=E19AC8E2797839BFE6892989708F1924&NickName=%u6e05%u98ce&Pic=http://imge.kugou.com/kugouicon/165/20220707/20220707143105836638.jpg&RegState=1&RegFrom=&t=42a909a834438be0137593611dbed7057e57fae20b86a43f6fc3eee2d08695f1&a_id=1014&ct=1712743944&UserName=%u006b%u0067%u006f%u0070%u0065%u006e%u0031%u0034%u0038%u0037%u0039%u0036%u0038%u0034%u0036%u0033&t1=; KugooID=1487968463; t=42a909a834438be0137593611dbed7057e57fae20b86a43f6fc3eee2d08695f1; a_id=1014; UserName=kgopen1487968463; mid=dbe66a98c0694c4dffebdb2228182609; dfid=11SGcS0c2kGQ06SxWR2Bw47W; Hm_lpvt_aedee6983d4cfc62f509129360d6bb3d=1712744161',
            'Referer':'https://www.kugou.com/'
        }
        # 负责获取第一个页面的数据
        self.queue1=Queue()
        #负责存储每一个音乐id 
        self.queue2=Queue()
        # 负责存储每一个音乐页面的内容
        self.queue3=Queue()
        # 负责存储每一首音乐的url
        self.queue4=Queue()
        self.queue5=Queue()
        # 生成一个锁对象
        self.lock=Lock()
        # 用来计数
        self.count=1
    def get_signature1(self):
        '''
        获得签名信息
        '''
        st='NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtappid=1014bitrate=0callback=callback123clienttime={}clientver=1000dfid=11SGcS0c2kGQ06SxWR2Bw47Wfilter=10inputtype=0iscorrection=1isfuzzy=0keyword={}mid=dbe66a98c0694c4dffebdb2228182609page=1pagesize=30platform=WebFilterprivilege_filter=0srcappid=2919token=42a909a834438be0137593611dbed705bfcd50a7eb8340f70f91663dcec2bb70userid=1487968463uuid=dbe66a98c0694c4dffebdb2228182609NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'.format(int(time.time()*1000),self.name)
        # 1、先转换成字符串
        # 2、读取js代码
        fun=''
        with open('D:/网络爬虫/爬虫小程序/酷狗爬虫多线程/signature.js','r',encoding='utf8') as f:
            fun=f.read()
        # 3、运行js代码
        js=execjs.compile(fun)
        res=js.call('ans',st)
        # 4、得到结果
        return res
    def get_signature2(self,id):
        '''
        获得第二个加密参数signature
        '''
        li=['NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt', 
            'appid=1014',
            f'clienttime={int(time.time()*1000)}',
            'clientver=20000',
            'dfid=11SGcS0c2kGQ06SxWR2Bw47W',
            f'encode_album_audio_id={id}',
            'mid=dbe66a98c0694c4dffebdb2228182609',
            'platid=4',
            'srcappid=2919',
            'token=42a909a834438be0137593611dbed705bfcd50a7eb8340f70f91663dcec2bb70',
            'userid=1487968463',
            'uuid=dbe66a98c0694c4dffebdb2228182609',
            'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'
            ]
        m5=hashlib.md5()
        m5.update(''.join(li).encode('utf8'))
        signature=m5.hexdigest()
        return signature
    def get_params(self):
        li=[
            {
                'callback': 'callback123',
                'srcappid': '2919',
                'clientver': '1000',
                'clienttime':f'{int(time.time()*1000)}',
                'mid': 'dbe66a98c0694c4dffebdb2228182609',
                'uuid': 'dbe66a98c0694c4dffebdb2228182609',
                'dfid': '11SGcS0c2kGQ06SxWR2Bw47W',
                'keyword': self.name,
                'page': n+1,
                'pagesize': 30,
                'bitrate': 0,
                'isfuzzy': 0,
                'inputtype': 0,
                'platform': 'WebFilter',
                'userid': '1487968463',
                'iscorrection': 1,
                'privilege_filter': 0,
                'filter': 10,
                'token': '42a909a834438be0137593611dbed705bfcd50a7eb8340f70f91663dcec2bb70',
                'appid': '1014' ,
                'signature':self.get_signature1()
            }  for n in range(1)
        ]
        for params in li:
            self.queue1.put(params)
    def get_data1(self):
        while True:
            try:
                params=self.queue1.get(timeout=3)
            except:
                break
            url='https://complexsearch.kugou.com/v2/search/song'
            try:
                res=requests.get(url,headers=self.headers1,params=params)
                self.queue2.put(res.text)
                self.queue1.task_done()
            except:
                continue
    def parse_data1(self):
        
        while True:
            try:
                    # 解析数据
                text=self.queue2.get(timeout=3)
            except:
                break
            # print(text[12:-2])
            text=text[12:-2]
            # json.loads()用法有两种
            # 1、将拥有字典形式的字符串转换为字符串
            # 2、将通过js文件形式读取过来的字符串也可以转换为python字典
            js_text=json.loads(text)#将字符串转换为字典形式
            id=[]
            id=jsonpath(js_text,'$..EMixSongID')
            try:
                for i in id:
                    self.queue3.put(i)
            except:
                continue
            self.queue2.task_done()
    
    def get_data2(self):

        while True:
            try:
                id_data=self.queue3.get(timeout=3)
            except:
                break
            url='https://wwwapi.kugou.com/play/songinfo'
            params={
                'srcappid': '2919',
                'clientver': '20000',
                'clienttime': f'{int(time.time()*1000)}',
                'mid': 'dbe66a98c0694c4dffebdb2228182609',
                'uuid': 'dbe66a98c0694c4dffebdb2228182609',
                'dfid': '11SGcS0c2kGQ06SxWR2Bw47W',
                'appid': '1014',
                'platid': 4,
                'encode_album_audio_id': id_data,
                'token': '42a909a834438be0137593611dbed705bfcd50a7eb8340f70f91663dcec2bb70',
                'userid': '1487968463',
                'signature':self.get_signature2(id_data)
            }
            try:
                res=requests.get(url,headers=self.headers2,params=params)
                self.queue4.put(res.json())
                self.queue3.task_done()
            except:
                continue
    
    def parse_data2(self):

        while True:
            try:
                text=self.queue4.get(timeout=3)
            except:
                break
            info=[]
            try:
                music_name=jsonpath(text,'$..audio_name')[0]
                music_url=jsonpath(text,'$..play_url')[0]
                music_jpg_url=jsonpath(text,'$..img')[0]
                info.append(music_name)
                info.append(music_url)
                info.append(music_jpg_url)
            except:
                continue
            self.queue5.put(info)
            self.queue4.task_done()

    def downloding(self):
        while True:
            try:
                info=self.queue5.get(timeout=3)
            except:
                break
            if not os.path.exists('D:/酷狗网站音乐'):
                os.makedirs('D:/酷狗网站音乐')
            os.chdir('D:/酷狗网站音乐')
            if not os.path.exists(self.name):
                os.mkdir(self.name)
            # 音乐下载
            if not os.path.exists(self.name+'/第'+str(self.count)+'首'):
                os.mkdir(self.name+'/第'+str(self.count)+'首')
            try:
                res=requests.get(info[1],headers=self.headers3,timeout=60)
            except:
                continue
            try:
                with open(self.name+'/第'+str(self.count)+'首/'+info[0]+'.mp3','wb') as f:
                    f.write(res.content)
                    print('第'+str(self.count)+'首的音乐下好了哦!')
                    # time.sleep(random.randint(1,3))
            except:
                continue
            # 图片下载
            try:
                res=requests.get(info[2],headers=self.headers3,timeout=60)
            except:
                continue
            try:
                with open(self.name+'/第'+str(self.count)+'首/'+info[0]+'.jpg','wb') as f:
                    f.write(res.content)
                    print('第'+str(self.count)+'首的图片下好了哦!')
                    self.count+=1
                    # time.sleep(random.randint(1,3))
            except:
                continue 
            self.queue5.task_done()

    
    def run(self):
        threads=[]
        # self.get_data1()
        t=Thread(target=self.get_params)
        # t.priority=0
        threads.append(t)
        for _ in range(5):
            t1=Thread(target=self.get_data1)
            threads.append(t1)
# 为第二个页面的数据的获取开了6个线程
        for _ in range(5):
            t=Thread(target=self.parse_data1)
            threads.append(t)
        
        # 为第二个页面数据的解析开了6个线程

        for _ in range(5):
            t=Thread(target=self.get_data2)
            threads.append(t)
        
        # 为下载开了6个线程

        for _ in range(5):
            t=Thread(target=self.parse_data2)
            threads.append(t)
        for _ in range(5):
            t=Thread(target=self.downloding)
            threads.append(t)
        # 开启线程
        for t in threads:
            t.start()
        # 等待所有线程结束
        for p in [self.queue1,self.queue2,self.queue3,self.queue4,self.queue5]:
            p.join()
    def run2(self):
        t=Thread(target=self.get_params)
        t.start()
        with ThreadPoolExecutor(max_workers=10) as tp:
            tp.submit(self.get_data1)
            tp.submit(self.parse_data1)
            tp.submit(self.get_data2)
            tp.submit(self.parse_data2)
            tp.submit(self.downloding)
if __name__=='__main__':
    name=input('请问你想要听什么歌曲:')
    kugou=KuGou(name)
    kugou.run2()
    print('结束!')
        
        